#include"syscall.h"
#include"console.h"
#include"global.h"
#include"syscall.h"
#include"thread.h"

#define _syscall0(NUM) ({   \
	int retval; \
	asm volatile( \
	"int $0x80" \
	:"=a"(retval) \
	:"a"(NUM)     \
	);   \
	retval; \
})

#define _syscall1(NUM,arg1) ({\
	int retval; \
	asm volatile( \
	"int $0x80" \
	:"=a"(retval) \
	:"0"(NUM),"b"(arg1) \
   	); \
	retval;	\
})

#define _syscall2(NUM,arg1,arg2) ({ \
	int retval; \
	asm volatile( \
	"int $0x80" \
	:"=a"(retval) \
	:"0"(NUM),"b"(arg1),"c"(arg2) \
   	); \
	retval;	\
})
	

#define _syscall3(NUM,arg1,arg2,arg3) ({ \
	int retval; \
	asm volatile( \
	"int $0x80" \
	:"=a"(retval) \
	:"0"(NUM),"b"(arg1),"c"(arg2),"d"(arg3) \
   	); \
	retval;	\
})

pid_t fork(void){
	return _syscall0(NR_FORK);
}

int32_t execv(const char* path,char** argv){
	return _syscall2(NR_EXEC,path,argv);
}

pid_t getpid(void){
	return _syscall0(NR_GETPID);
}

void clear(void){
	_syscall0(NR_CLEAR);
}

int write(int fd,void* buffer,int len){
	return _syscall3(NR_WRITE,fd,buffer,len);
}

char* getcwd(char* buffer,uint32_t size){
	return (char*)_syscall2(NR_GETCWD,buffer,size);
}

int32_t mkdir(const char* path){
	return _syscall1(NR_MKDIR,path);
}

int32_t rmdir(const char* path){
	return _syscall1(NR_RMDIR,path);
}

int32_t chdir(const char* path){
	return _syscall1(NR_CHDIR,path);
}

struct dir* opendir(const char* path){
	return (struct dir*)_syscall1(NR_OPENDIR,path);
}

int32_t closedir(struct dir* d){
	return _syscall1(NR_CLOSEDIR,d);
}

struct dir_entry* readdir(struct dir* d){
	return (struct dir_entry*)_syscall1(NR_READDIR,d);
}

void rewinddir(struct dir* d){
	_syscall1(NR_REWINDDIR,d);
}

int32_t stat(const char* path,struct stat* st){
	return _syscall2(NR_STAT,path,st);	
}

void ps(void){
	_syscall0(NR_PS);
}

int read(int fd,void* buffer,int len){
	return _syscall3(NR_READ,fd,buffer,len);
}

void putchar(char c){
	_syscall1(NR_PUTCHAR,c);
}

void* malloc(uint32_t size){
	return (void*)_syscall1(NR_MALLOC,size);
}

void free(void* addr){
	_syscall1(NR_FREE,addr);
}

pid_t wait(int32_t *status){
	return (pid_t)_syscall1(NR_WAIT,status);
}

void exit(int status){
	_syscall1(NR_EXIT,status);
}
